package com.java.jvalidator.framework.validator;

import java.util.Date;

import com.java.jvalidator.framework.TypeUtil;
import com.java.jvalidator.framework.ValidationException;
import com.java.jvalidator.framework.ValidationExceptionMsg;
import com.java.jvalidator.framework.config.Parameters;

public class CompareValidator extends AbstractValidator {
	private static Validator instance = new CompareValidator();

	public static Validator getInstance() {
		return instance;
	}

	protected boolean beginValidate(Object target, String fieldName, Parameters param) throws ValidationException {
		Object fieldValue = TypeUtil.getPropertyValue(target, fieldName);

		if (fieldValue == null) {
			return true;
		}
		String compareWith = param.getParameterValueAsString("compareWith");
		String comparison = TypeUtil.trimString(param.getParameterValueAsString("comparison"));

		if (TypeUtil.isStringNullOrEmpty(comparison)) {
			comparison = "eq";
		}
		if (TypeUtil.isStringNullOrEmpty(compareWith)) {
			throw new ValidationException(ValidationExceptionMsg.VALIDATION_ERROR);
		}
		Object compareValue = TypeUtil.getPropertyValue(target, compareWith);
		if (compareValue == null) {
			return true;
		}

		return validateValue(fieldValue, compareValue, comparison);
	}

	private boolean validateValue(Object fieldValue, Object compareValue, String comparison) throws ValidationException {
		boolean bothNumber = (TypeUtil.isDigital(fieldValue)) && (TypeUtil.isDigital(compareValue));
		boolean sameClass = fieldValue.getClass().getName().equals(compareValue.getClass().getName());

		if ((!sameClass) && (!bothNumber)) {
			throw new ValidationException("Sorry,the two types can't compare!");
		}
		if ((fieldValue instanceof Date))
			return compareDate(fieldValue, comparison, compareValue);
		if (TypeUtil.isDigital(fieldValue)) {
			return compareDigital(fieldValue, comparison, compareValue);
		}
		return fieldValue.equals(compareValue) == comparison.equalsIgnoreCase("eq");
	}

	private boolean compareDigital(Object fieldValue, String comparison, Object compareValue) throws ValidationException {
		double value1 = TypeUtil.convertNumberToDouble(fieldValue);
		double value2 = TypeUtil.convertNumberToDouble(compareValue);
		int compare = 0;
		if (value1 < value2)
			compare = -1;
		else if (value1 > value2)
			compare = 1;
		else {
			compare = 0;
		}
		return compareResult(comparison, compare);
	}

	private boolean compareDate(Object fieldValue, String comparison, Object compareValue) {
		Date fieldDate = (Date) fieldValue;
		Date compareDate = (Date) compareValue;
		int compare = fieldDate.compareTo(compareDate);
		return compareResult(comparison, compare);
	}
}
